package com.sunshine.controller;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.baomidou.mybatisplus.plugins.Page;
import com.sunshine.common.pojo.SearchLog;
import com.sunshine.common.utils.FmmResult;
import com.sunshine.common.utils.LoggerUtils;
import com.sunshine.pojo.Log;
import com.sunshine.service.AppLogService;
import com.sunshine.service.impl.AppLogServiceImpl;

/**
 * 日志管理的控制层
 * 执行日志文件解析功能
 * 
 * @author NGU-sunshine
 *
 */
@Controller
public class AppLogController {
	// 创建存放日志对象的队列
	private static final ConcurrentLinkedQueue<Log> logQueue = new ConcurrentLinkedQueue<Log>();
	// 定义成员变量接收解析后的string
	private String rawString;

	// 构造方法中执行解析日志功能
	public AppLogController() {
		try {
			paseTheFile();
		} catch (ParseException e) {
			//记录日志
			LoggerUtils.error(e);
			e.printStackTrace();
		}
	}

	// 注入AppLogService
	@Autowired
	private AppLogService appLogService;

	/**
	 * 默认跳转到log页面
	 * 
	 * @return 转到log页面
	 */
	@RequestMapping("/")
	public String showIndex() {
		// 记录日志
		LoggerUtils.info("somebody访问首页");
		// 重定向到页面显示页
		return "redirect:/list";
	}

	/**
	 * 对外暴露restful接口插入日志数据，每调用一次插入一条数据
	 * @param model 通过Model返回数据
	 * @return 返回插入成功和失败对应的视图
	 */
	@RequestMapping("/add")
	public String getItemById(Model model) {
		// 记录日志
		LoggerUtils.info("somebody进行add操作");
		// 获取一条需要插入的日志
		Log log = getALog();
		// 调用sercice插入
		FmmResult insertLog = appLogService.insertLog(log);
		// 根据状态吗判断是否插入成功
		if (insertLog.getStatus() == 200) {
			// 记录日志
			LoggerUtils.info("somebody add操作成功");
			// 重定向到页面显示页
			return "redirect:/list";
		}
		// 记录日志
		LoggerUtils.info("somebody add操作失败");
		// 跳转到插入失败页面
		return "fail";
	}

	/**
	 * 页面查询功能实现
	 * @param model 通过Model返回数据
	 * @return 返回查询结果集
	 */
	@RequestMapping("/list")
	public String getLogList(Model model) {
		// 查询Log内容列表
		SearchLog searchLog = new SearchLog();
		Page<Log> page = appLogService.getLogList(searchLog);
		// List<Log> logList = page.getRecords();
		System.out.println(page.getRecords());
		// 把结果传递给页面
		model.addAttribute("page", page);
		return "log";
	}

	/**
	 * 带条件的页面查询功能实现
	 * 
	 * @param searchLog  输入参数封装类
	 * @param model 通过Model返回数据          
	 * @return 返回查询结果集
	 */
	@RequestMapping(value = "/query", method = RequestMethod.POST)
	public String getLogListByQuery(SearchLog searchLog, Model model) {
		// 查询Log内容列表
		Page<Log> page = appLogService.getLogList(searchLog);
		// List<Log> logList = page.getRecords();
		// 把结果传递给页面
		model.addAttribute("page", page);
		model.addAttribute("searchLog", searchLog);
		return "log";
	}

	/**
	 * 日志文件处理工作
	 * 
	 * @throws ParseException
	 * 
	 */
	private void paseTheFile() throws ParseException {
		// 1.获取文件位置
		String path = AppLogServiceImpl.class.getClassLoader().getResource("fmm-qplatform.log").getPath();
		// 2把文件通过流方式读取进来
		try (FileInputStream fis = new FileInputStream(path);
				BufferedReader br = new BufferedReader(new InputStreamReader(fis, "GBK"));) {
			String line = null;
			// 建立StringBuilder获取每行数据
			StringBuilder sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				// StringBuilder存储每行数据
				sb.append(line);
				// 添加换行符
				sb.append("\r\n");
			}
			rawString = sb.toString();
		} catch (Exception e) {
			LoggerUtils.error("文件操作异常", e);
			e.printStackTrace();
		}
		// 3.通过正则表达式获取到每条日志信息，根据日志创建Log对象，存放到队列中
		String regex = "(\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}:\\d{2}),\\d{3}\\s\\[(.*)\\]\\[(.*)\\]\\s(.*)\\s-\\s(.*)";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(rawString);
		while (m.find()) {
			String logTime = m.group(1);
			// 2015-05-28 16:13:46
			// 把string转为date类型
			DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date logtime = df.parse(logTime);
			// 通过正则组获取threadName
			String threadName = m.group(2);
			// 通过正则组获取logLeval
			String logLeval = m.group(3);
			// 通过正则组获取className
			String className = m.group(4);
			// 通过正则组获取logInfo
			String logInfo = m.group(5);
			// 生成Log对象
			Log log = new Log(logtime, threadName, logLeval, className, logInfo);
			// 把Log对象插入队列中去
			boolean flag = logQueue.offer(log);
			if (flag) {
				LoggerUtils.info("Log对象，成功存放到队列中");
			} else {
				LoggerUtils.info("Log对象存放到队列中失败");
			}
		}

	}

	/**
	 * 从队列中获取一条日志记录
	 * 
	 * @return 一条日志记录
	 */
	private Log getALog() {
		if (logQueue.isEmpty()) {
			return null;
		}
		Log log = (Log) logQueue.poll();
		return log;
	}

}
